package com.humi.partner.common.utils;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFCell;
import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.web.multipart.MultipartFile;

import com.alibaba.druid.util.StringUtils;
import com.humi.cloud.common.exception.HumiRuntimeException;
import com.humi.cloud.common.model.ResponseCode;
import com.humi.partner.common.utils.po.ExcelColumnPO;
import com.humi.partner.common.utils.po.ExcelImportPO;

import lombok.extern.slf4j.Slf4j;

/**
 * @描述：测试excel读取 导入的jar包
 *               <p>
 *               poi-3.8-beta3-20110606.jar
 *               <p>
 *               poi-ooxml-3.8-beta3-20110606.jar
 *               <p>
 *               poi-examples-3.8-beta3-20110606.jar
 *               <p>
 *               poi-excelant-3.8-beta3-20110606.jar
 *               <p>
 *               poi-ooxml-schemas-3.8-beta3-20110606.jar
 *               <p>
 *               poi-scratchpad-3.8-beta3-20110606.jar
 *               <p>
 *               xmlbeans-2.3.0.jar
 *               <p>
 *               dom4j-1.6.1.jar
 *               <p>
 *               jar包官网下载地址：http://poi.apache.org/download.html
 *               <p>
 *               下载poi-bin-3.8-beta3-20110606.zipp
 */
@Slf4j
public class ImportExecl {
	/**
	 * 总行数
	 */
	private int totalRows = 0;
	/**
	 * 总列数
	 */
	private int totalCells = 0;
	/**
	 * 错误信息
	 */
	private String errorInfo;

	/**
	 * 构造方法
	 */
	public ImportExecl() {
	}

	public int getTotalRows() {
		return totalRows;
	}

	public int getTotalCells() {
		return totalCells;
	}

	public String getErrorInfo() {
		return errorInfo;
	}

	public boolean validateExcel(String filePath) {
		/** 检查文件名是否为空或者是否是Excel格式的文件 */
		if (filePath == null || !(WDWUtil.isExcel2003(filePath) || WDWUtil.isExcel2007(filePath))) {
			errorInfo = "文件名不是excel格式";
			return false;
		}
		/** 检查文件是否存在 */
		File file = new File(filePath);
		if (file == null || !file.exists()) {
			errorInfo = "文件不存在";
			return false;
		}
		return true;
	}

	/**
	 * 
	 * <pre>
	 *	获取excel sheet0数据
	 * </pre>
	 * 
	 * @param excel 数据结构
	 * @return DB
	 */
	public List<Map<String, Object>> importExcel(ExcelImportPO excel) {
		XSSFSheet sheet = null;
		XSSFWorkbook importBook = null;
		InputStream in = null;
		try {
			in = excel.getFile().getInputStream();
			importBook = new XSSFWorkbook(in);
			sheet = importBook.getSheetAt(0);
			// 解析excel
			return getContent(sheet, excel.getColumns());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
			throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "excel文件错误");
		} finally {
			try {
				if (importBook != null) {
					importBook.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "文件关闭出错");
			}
		}
	}

	/**
	 * 
	 * <pre>
	 *	获取excel sheet0数据
	 * </pre>
	 * @param file excel多媒体文件
	 * @param columns 取值规则
	 * @param startIndex 开始的行号（1 base）
	 * @return
	 */
	public List<Map<String, Object>> importExcel(MultipartFile file, List<ExcelColumnPO> columns, int startIndex) {
		if(startIndex<1) {
			return new ArrayList<>();
		}
		startIndex-=1;
		XSSFSheet sheet = null;
		XSSFWorkbook importBook = null;
		InputStream in = null;
		try {
			in = file.getInputStream();
			importBook = new XSSFWorkbook(in);
			sheet = importBook.getSheetAt(0);
			// 解析excel
			return getContent(sheet, columns, startIndex);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
			throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "excel文件错误");
		} finally {
			try {
				if (importBook != null) {
					importBook.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "文件关闭出错");
			}
		}
	}
	
	/**
	 * 
	 * <pre>
	 *	获取excel sheet0数据
	 * </pre>
	 * @param file 
	 * @param startIndex 开始行号(1 base)
	 * @return
	 */
	public List<List<Object>> importExcel(MultipartFile file, int startIndex) {
		if(startIndex<1) {
			return new ArrayList<>();
		}
		startIndex-=1;
		XSSFSheet sheet = null;
		XSSFWorkbook importBook = null;
		InputStream in = null;
		try {
			in = file.getInputStream();
			importBook = new XSSFWorkbook(in);
			sheet = importBook.getSheetAt(0);
			// 解析excel
			return getContent(sheet,startIndex);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error(e.getMessage());
			throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "excel文件错误");
		} finally {
			try {
				if (importBook != null) {
					importBook.close();
				}
				if (in != null) {
					in.close();
				}
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				throw HumiRuntimeException.newInstance(ResponseCode.FAILED, "文件关闭出错");
			}
		}
	}

	/**
	 * 
	 * <pre>
	 * 获取sheet的数据
	 * </pre>
	 * 
	 * @param sheet
	 * @param excelTitle
	 * @return DB
	 */
	private List<Map<String, Object>> getContent(XSSFSheet sheet, List<ExcelColumnPO> excelTitle) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		for (int i = 3; i < sheet.getPhysicalNumberOfRows(); i++) {
			Map<String, Object> Msg = new HashMap<String, Object>();
			for (int j = 0; j < excelTitle.size(); j++) {
				Object value = getCellValue(sheet.getRow(i).getCell(excelTitle.get(j).getColumnIndex() - 1));
				Msg.put(StringUtils.isEmpty(excelTitle.get(j).getColumnField()) ? "field" + i + j
						: excelTitle.get(j).getColumnField(), value);
			}
			Msg.put("__rowIndex", i + 1);
			list.add(Msg);
		}
		return list;
	}
	
	/**
	 * 
	 * <pre>
	 *	TODO
	 * </pre>
	 * @param sheet
	 * @param startRow 开始的行号（0 base）
	 * @return
	 */
	private List<List<Object>> getContent(XSSFSheet sheet,int startRow) {
		List<List<Object>> list = new ArrayList<List<Object>>();
		for (int i = startRow; i < sheet.getPhysicalNumberOfRows(); i++) {
			List<Object> Msg = new ArrayList<>();
			int cellNum=sheet.getRow(i).getPhysicalNumberOfCells();
			for (int j = 0; j < cellNum; j++) {
				Object value = getCellValue(sheet.getRow(i).getCell(j));
				Msg.add(value);
			}
			list.add(Msg);
		}
		return list;
	}

	/**
	 * 
	 * <pre>
	 *	获取sheet数据
	 * </pre>
	 * @param sheet
	 * @param excelTitle 取值规则
	 * @param rowStart 开始的行号（0 base）
	 * @return  List<Map<String, Object>>
	 */
	private List<Map<String, Object>> getContent(XSSFSheet sheet, List<ExcelColumnPO> excelTitle, int rowStart) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		for (int i = rowStart; i < sheet.getPhysicalNumberOfRows(); i++) {
			Map<String, Object> Msg = new HashMap<String, Object>();
			for (int j = 0; j < excelTitle.size(); j++) {
				Object value = getCellValue(sheet.getRow(i).getCell(excelTitle.get(j).getColumnIndex() - 1));
				Msg.put(StringUtils.isEmpty(excelTitle.get(j).getColumnField()) ? "__cell"+ j
						: excelTitle.get(j).getColumnField(), value);
			}
			Msg.put("__rowIndex", i + 1);
			list.add(Msg);
		}
		return list;
	}

	/**
	 * 
	 * <pre>
	 * 获取单元格的数据
	 * </pre>
	 * 
	 * @param cell
	 * @return Object
	 */
	private Object getCellValue(XSSFCell cell) {
		if (null == cell) {
			return "";
		}
		Object cellValue;
		// 以下是判断数据的类型
		switch (cell.getCellType()) {
		case HSSFCell.CELL_TYPE_NUMERIC: // 数字
			if (DateUtil.isCellDateFormatted(cell)) {
				// 如果是date类型则 ，获取该cell的date值
				cellValue = HSSFDateUtil.getJavaDate(cell.getNumericCellValue());
			} else {// 纯数字
				cellValue = BigDecimal.valueOf(cell.getNumericCellValue());
			}
			break;
		case HSSFCell.CELL_TYPE_STRING: // 字符串
			cellValue = cell.getStringCellValue();
			break;
		case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
			cellValue = cell.getBooleanCellValue() + "";
			break;
		case HSSFCell.CELL_TYPE_FORMULA: // 公式
			cellValue = BigDecimal.valueOf(cell.getNumericCellValue());// 使用公式解析，获取到的是公式的结果值
			break;
		case HSSFCell.CELL_TYPE_BLANK: // 空值
			cellValue = "";
			break;
		case HSSFCell.CELL_TYPE_ERROR: // 故障
			cellValue = "";
			break;
		default:
			cellValue = "";
			break;
		}
		return cellValue;
	}

	public List<List<String>> read(String filePath) {
		List<List<String>> dataLst = new ArrayList<List<String>>();
		InputStream is = null;
		try {
			/** 验证文件是否合法 */
			if (!validateExcel(filePath)) {
				System.out.println(errorInfo);
				return null;
			}
			/** 判断文件的类型，是2003还是2007 */
			boolean isExcel2003 = true;
			if (WDWUtil.isExcel2007(filePath)) {
				isExcel2003 = false;
			}
			/** 调用本类提供的根据流读取的方法 */
			File file = new File(filePath);
			is = new FileInputStream(file);
			dataLst = read(is, isExcel2003);
			is.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		} finally {
			if (is != null) {
				try {
					is.close();
				} catch (IOException e) {
					is = null;
					e.printStackTrace();
				}
			}
		}
		/** 返回最后读取的结果 */
		return dataLst;
	}

	public List<List<String>> read(InputStream inputStream, boolean isExcel2003) {
		List<List<String>> dataLst = null;
		try {
			/** 根据版本选择创建Workbook的方式 */
			Workbook wb = null;
			if (isExcel2003) {
				wb = new HSSFWorkbook(inputStream);
			} else {
				wb = new XSSFWorkbook(inputStream);
			}
			dataLst = read(wb);
		} catch (IOException e) {

			e.printStackTrace();
		}
		return dataLst;
	}

	private List<List<String>> read(Workbook wb) {
		FormulaEvaluator formulaEvaluator = null;// 用来解析公式类
		List<List<String>> dataLst = new ArrayList<List<String>>();
		// 判断文件类型来判断应该使用哪个解析公式类
		String className = wb.getClass().getName();
		if (className.equals("HSSFWorkbook")) {// 2003
			formulaEvaluator = new HSSFFormulaEvaluator((HSSFWorkbook) wb);
		} else {
			formulaEvaluator = new XSSFFormulaEvaluator((XSSFWorkbook) wb);
		}
		/** 得到第一个shell */
		Sheet sheet = wb.getSheetAt(0);
		/** 得到Excel的行数 */
		this.totalRows = sheet.getPhysicalNumberOfRows();
		/** 得到Excel的列数 */
		if (this.totalRows >= 1 && sheet.getRow(0) != null) {
			this.totalCells = sheet.getRow(0).getPhysicalNumberOfCells();
		}
		/** 循环Excel的行 */
		for (int r = 0; r < this.totalRows; r++) {
			Row row = sheet.getRow(r);
			if (row == null) {
				continue;
			}
			List<String> rowLst = new ArrayList<String>();
			/** 循环Excel的列 */
			for (int c = 0; c < this.getTotalCells(); c++) {
				Cell cell = row.getCell(c);
				String cellValue = "";
				if (null != cell) {
					// 以下是判断数据的类型
					switch (cell.getCellType()) {
					case HSSFCell.CELL_TYPE_NUMERIC: // 数字
						DecimalFormat df = new DecimalFormat("######0"); // 四色五入转换成整数
						cellValue = df.format(cell.getNumericCellValue());
						break;
					case HSSFCell.CELL_TYPE_STRING: // 字符串
						cellValue = cell.getStringCellValue();
						break;
					case HSSFCell.CELL_TYPE_BOOLEAN: // Boolean
						cellValue = cell.getBooleanCellValue() + "";
						break;
					case HSSFCell.CELL_TYPE_FORMULA: // 公式
						cellValue = String.valueOf((int) (formulaEvaluator.evaluate(cell).getNumberValue()));// 使用公式解析，获取到的是公式的结果值
						break;
					case HSSFCell.CELL_TYPE_BLANK: // 空值
						cellValue = "";
						break;
					case HSSFCell.CELL_TYPE_ERROR: // 故障
						cellValue = "非法字符";
						break;
					default:
						cellValue = "未知类型";
						break;
					}
				}
				rowLst.add(cellValue);
			}
			/** 保存第r行的第c列 */
			dataLst.add(rowLst);
		}
		return dataLst;
	}

	public static void main(String[] args) throws Exception {
		ImportExecl poi = new ImportExecl();
		// List<List<String>> list = poi.read("d:/aaa.xls");
		List<List<String>> list = poi.read("E:\\360humi\\src\\main\\webapp\\fileupload\\店铺基本信息标准模板.xlsx");
		if (list != null) {
			for (int i = 0; i < list.size(); i++) {
				System.out.print("第" + (i) + "行");
				List<String> cellList = list.get(i);
				for (int j = 0; j < cellList.size(); j++) {
					// System.out.print(" 第" + (j + 1) + "列值：");
					System.out.print("    " + cellList.get(j));
				}
				System.out.println();
			}
		}
	}

}

class WDWUtil {
	public static boolean isExcel2003(String filePath) {
		return filePath.matches("^.+\\.(?i)(xls)$");
	}

	public static boolean isExcel2007(String filePath) {
		return filePath.matches("^.+\\.(?i)(xlsx)$");
	}
}